/*
 * Author: Jinfeng Zhuang, 2024.Week16
 *
 * Compatible with ANSI-C.
 */

#include <string.h>

typedef unsigned char U8;
typedef unsigned int  U32;

struct ringbuf
{
    U8 *buf;
    U32 size;
    U32 wr;
    U32 rd;
};

/* Return: bytes put to ringbuf */
int ringbuf_put(struct ringbuf *r, U8 *buf, U32 len)
{
    U32 remain = r->size - (r->wr - r->rd);
    U32 reallen = (remain > len) ? len : remain;
    U32 wr = r->wr % r->size;
    U32 part1 = r->size - wr;
    U32 part2 = reallen - part1;
    
    if (part1 >= reallen)
    {
        memcpy(&r->buf[wr], buf, reallen);
    }
    else
    {
        memcpy(&r->buf[wr], buf, part1);
        memcpy(&r->buf[0], &buf[part1], part2);
    }
    
    r->wr += reallen;
    
    return reallen;
}

/* Return: bytes get from ringbuf */
int ringbuf_get(struct ringbuf *r, U8 *buf, U32 len)
{
    U32 remain = r->wr - r->rd;
    U32 reallen = (remain > len) ? len : remain;
    U32 rd = r->rd % r->size;
    U32 part1 = r->size - rd;
    U32 part2 = reallen - part1;
    
    if (part1 >= reallen)
    {
        memcpy(buf, &r->buf[rd], reallen);
    }
    else
    {
        memcpy(buf, &r->buf[rd], part1);
        memcpy(&buf[part1], &r->buf[0], part2);
    }
    
    r->rd += reallen;
    
    return reallen;
}
